package tp.pr5.mv.window;

import java.awt.Color;
import java.awt.FlowLayout;

import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import tp.pr5.mv.CPU;
import tp.pr5.mv.Instruction;
import tp.pr5.mv.Memory;
import tp.pr5.mv.OperandStack;
import tp.pr5.mv.ProgramCounter;
import tp.pr5.mv.ProgramMV;

@SuppressWarnings("serial")
public class BarraEstado extends JPanel implements CPU.Observer, OperandStack.Observer, Memory.Observer {

	private JLabel estaParada;
	private JLabel numInst;
	private JLabel pila;
	private JLabel memoria;
	private JCheckBox pilaCheckBox;
	private JCheckBox memoriaCheckBox;
	private int instEjecutadas;
	
	private boolean pilaModif;
	private boolean memModif;
	
	public BarraEstado() {
		
		super(new FlowLayout());
		init();
	}
	
	
	public void init() {
		
		
		pilaModif = false;
		memModif = false;
		
		estaParada = new JLabel("Máquina parada.");  
		estaParada.setVisible(false);
		add(estaParada);
		
		instEjecutadas = 0;
		
		numInst = new JLabel("Num. Instrucciones ejecutadas:" + instEjecutadas );
		add(numInst);
		
		memoriaCheckBox = new JCheckBox();
		memoriaCheckBox.setEnabled(false);
		add(memoriaCheckBox);
		
		memoria = new JLabel("Memoria modificada");
		add(memoria);
		
		
		pilaCheckBox = new JCheckBox(); 
		pilaCheckBox.setEnabled(false);
		add(pilaCheckBox);
		
		
		pila = new JLabel("Pila modificada");
		add(pila);
		
	}
	
	public void onStartInstrExecution(Instruction ins) {
		
		pilaModif = false;
		memModif = false;
		
		SwingUtilities.invokeLater(
				new Runnable() {
				 		public void run() {
				 			pilaCheckBox.setSelected(pilaModif);
				 			memoriaCheckBox.setSelected(memModif);
				 		}
				}
		);
		
		
	}
	public void onEndInstrExecution(Instruction instr, Memory mem, OperandStack stack, ProgramCounter pc) {
		
		SwingUtilities.invokeLater(
				new Runnable() {
				 		public void run() {
				 			
				 			
				 			pilaCheckBox.setSelected(pilaModif);
				 			memoriaCheckBox.setSelected(memModif);
				 			
				 			numInst.setForeground(Color.black); // Cuando la instrucción termina se setean los JLabel a negro por si estuvieran pintados de rojo tras una excepción
				 			pila.setForeground(Color.black);
				 			memoria.setForeground(Color.black);
				 			
				 			
				 			instEjecutadas++;
				 			numInst.setText("Num. Instrucciones ejecutadas:" + instEjecutadas);
				 		}
				}
		);
		
	}
	
	public void onHalt() {
		
		SwingUtilities.invokeLater(
				new Runnable() {
				 		public void run() {
				 			estaParada.setVisible(true);
				 			estaParada.setForeground(Color.red);
				 		}
				}
		);

	}
	
	public void onReset(ProgramMV program) {     
		
		SwingUtilities.invokeLater(
				new Runnable() {
				 		public void run() {
				 			instEjecutadas = 0;
				 			estaParada.setVisible(false);
				 			memoriaCheckBox.setSelected(false);
				 			pilaCheckBox.setSelected(false);
				 		}
				}
		);
		
		
	}
	
	public void onStartRun() {
		
		SwingUtilities.invokeLater(
				new Runnable() {
				 		public void run() {
				 			memoriaCheckBox.setSelected(false);
				 			pilaCheckBox.setSelected(false);
				 		}
				}
		);
		
	}
	
	public void onEndRun(boolean aborted) {}
	
	public void onTrap(Instruction instr, String trapMessage) {
		
		SwingUtilities.invokeLater(
				new Runnable() {
				 		public void run() {
				 			numInst.setForeground(Color.red);       // Ponemos el color de fuente en rojo.
				 			pila.setForeground(Color.red);
				 			memoria.setForeground(Color.red);
				 		}
				}
		);
	}
	
	
	public void onPop(int val) {
		pilaModif = true;
	}
	
	public void onPush(int val) {
		pilaModif = true;
	}
	
	public void onReset() {
		pilaModif = true;
		memModif = true;
	}
	
	public void onWrite(int pos, int val) {
		memModif = true;
	}
	
}

